home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Languages / Mops 2.7 / Mops source / Toolbox classes / AppleEvents < prev    next >
Encoding:
Text File  |  1995-07-06  |  7.6 KB  |  266 lines  |  [TEXT/MSET]

  1. \ 10Dec93 DBH  initial version
  2. \ 12Feb94 DBH added proper disposal of AppleEvent and Reply via AEDisposeDesc at each and
  3. \ every time we send an AppleEvent. Before, this was causing memory to be consumed and never
  4. \ freed at each send.
  5.  
  6.  \ It is interesting that, with this scheme at least, it is
  7.  \ not necessary to create and dispose the description record QEdesc at each send.
  8.  
  9. \ See general comments at the end of this file.
  10.  
  11.  
  12. \ This AppleEvent class is at the moment geared to sending AEs to
  13. \ Quick Edit.  But it wouldn't be too hard to make it more general.
  14.  
  15.  
  16. :class AEDesc super{ object }
  17.  
  18. record
  19. {    longword    descriptorType
  20.     handle        dataHandle        \ first 4 bytes of handle will = MSET after new:
  21.     var            dataPtr
  22. }
  23.  
  24. :m classinit:
  25.     'type MSET put: dataPtr    \ put QE creator signature in a dataPtr
  26.     ;m
  27.  
  28. :m new:
  29.     word0        \ room for result
  30.     'type sign    \ typeApplSignature
  31.     addr: dataPtr
  32.     8            \ dataSize
  33.     ^base        \ VAR result -> our record
  34.     call AECreateDesc
  35.     i->l
  36.     0= not IF ." failed to create AE Desc record" THEN
  37.     ;m
  38.  
  39. :m release:
  40.     word0        \ room for result
  41.     ^base        \ VAR theAEDesc -> our record
  42.     call AEDisposeDesc  \ here we actually use AEDisposeDesc to dispose an AEDesc
  43.     i->l
  44.      0= not IF ." failed to dispose AE Desc record" THEN
  45.     ;m
  46.  
  47. ;class
  48.  
  49. AEDesc QEdesc
  50.  
  51.  
  52.  
  53. variable dummyReply 16 allot
  54.  
  55. :class AppleEvent super{ object }
  56.  
  57. record
  58. {    int    what
  59.     var    mclass
  60.     var    when
  61.     var    mID
  62.     int    modifiers
  63.     var theClass    \ will be 'type OPEN or TEXT for now.  Could be other things later.
  64. }
  65.  
  66. \ :m classinit: \ 12Feb94 DBH   necessary???  apparently not
  67. \    konst kHighLevelEvent put: what ;m
  68.  
  69. \ Guess what?  We have to dispose of our AppleEvent AFTER EACH SEND !
  70. \ and we must use AEDisposeDesc.  This was not immediately obvious to me from IM.
  71. \ Also, we must dispose of our reply, again using AEDisposeDesc.  AEDisposeDesc seems to be
  72. \ the universal dispoz-all for AE things.  The penalty for not doing this is lost heap at every
  73. \ send.
  74.  
  75. :m release:     \ 12Feb94 DBH
  76.     word0    \ room for result
  77.     ^base call AEDisposeDesc
  78.     i->l
  79.      0= not IF ." failed to dispose of AppleEvent" THEN
  80.     
  81.     word0    \ room for result
  82.     dummyReply call AEDisposeDesc
  83.     i->l
  84.      0= not IF ." failed to dispose of Reply" THEN
  85.     ;m
  86.  
  87. :m new:    { theClass theID -- }    \ theID MUST be a handle
  88.     word0    \ room for result
  89.     theClass
  90.     theID
  91.     QEdesc    \ we are always using this target here
  92.     konst kAutoGenerateReturnID makeint
  93.     0    \ konst AnyTransactionID \ no call?
  94.     ^base    \ VAR result will be our own ivar record , but only using ivars through modifiers
  95.     call AECreateAppleEvent i->l
  96.     0<> IF " failed to create AppleEvent" cr THEN ;m
  97.  
  98. \ :m set:  ( AEEventClass -- ) \ 12Feb94 DBH incorporated into new:
  99. \    put: theClass ;m
  100.  
  101. :m send:    ( -- oserr )
  102.     word0    \ room for result
  103.     ^base    \ we are sending ourself, of course
  104.     dummyReply
  105.     konst kAEWaitReply \ sendmode, we must wait for reply so we don't clobber the handle
  106.                         \ before QE has a chance to deal with it.
  107.     konst kAENormalPriority makeint        \ sendPriority
  108.     konst kAEDefaultTimeout    \ timeoutinticks  see IM-VI 6-94
  109.     0    \ idleproc
  110.     0    \ filterproc
  111.     call AESend i->l
  112.     ;m
  113.     
  114.  
  115. ;class
  116.  
  117.  
  118. :class QEopen super{ object }
  119.  
  120. record
  121. {    byte fileNameLength
  122.     32 bytes fileName
  123.     int volRef#
  124.     var dirID
  125.     var selStart
  126.     var SelEnd
  127. }
  128.  
  129. :m put: { ^obj n1 n2 -- }    \  file object and desired selection range
  130.     getname: [ ^obj ]  ( addr len )
  131.     32 min  dup put: fileNameLength  addr: fileName  swap  cmove    \ ala ctl example
  132.     
  133.     getvref: [ ^obj ]  put: volRef#
  134.     getdirID: [ ^obj ]  put: dirID
  135.     n1 put: selStart
  136.     n2 put: SelEnd ;m
  137.  
  138. :m length:  ( -- n )  \ can't send this message to an ivar!!
  139.     48 ;m
  140.  
  141. ;class
  142.  
  143. \ This class will be used as our sole communication device to QE when sending AEs.
  144. :class QE super{ object }
  145.  
  146.     AppleEvent    QEevent
  147.     QEopen        tQEopen
  148.     string+        QEstr
  149.  
  150. :m new:
  151.     new: QEstr
  152.     new: QEdesc        \ note that QEdesc is a public object
  153.     ;m
  154.  
  155. :m release:
  156.     release: QEstr
  157.     release: QEdesc
  158.     ;m
  159.  
  160. :m send:  ( theClass -- oserr ) \ 12Feb94 DBH must new: and release: for each send!!
  161.     handle: QEstr ( ID )  new: QEevent    \ always using QEstr handle as our ID.  
  162.     send: QEevent
  163.     clear: QEstr    \ 12Feb94 DBH must always clear the string because next action
  164.                     \ may be to simply add as when doing a text:
  165.     release: QEevent
  166.     ;m
  167.  
  168. :m openFile:  ( ^obj n1 n2 -- oserr )    \ file object and selection range
  169.     put: tQEopen
  170.     addr: tQEopen  length: tQEopen  put: QEstr
  171.     'type OPEN  send: self ;m
  172.  
  173. :m text:  ( addr len -- )        \ text to be "typed" into front QE window
  174.                                     \ if no window open in QE, no action from QE, just a beep
  175. \    put: QEstr     \ 27Jan94 DBH
  176. \    'type TEXT send: self ;m
  177.     add: QEstr ;m
  178.  
  179. variable emitvar 4 allot
  180.  
  181. :m cr:    ( -- oserr )
  182.     13 emitvar c!
  183.     emitvar 1 text: self
  184.     'type TEXT send: self
  185.     clear: QEstr ;m
  186.  
  187. :m newWindow: ( addr len -- oserr )    \ opens a new window in QE, does not create a file on disk
  188.                                     \ if no more available windows in QE, no action, just a beep
  189.     put: QEstr
  190.     'type NEWF send: self ;m
  191.  
  192. :m putRect:  ( l t r b -- oserr )    \ will set the front QE window portrect to these values
  193.                                     \ if no window open in QE, no action from QE, just a beep
  194.     put: temprect
  195.     addr: temprect 8 put: QEstr
  196.     'type RECT  send: self ;m
  197.  
  198. :m find:  ( addr len -- oserr )  \ will request that QE find first occurrence of
  199.     \ the given text in the front qe window.  We are limited to strings of length
  200.     \ 255 and less.  All searches will be case insensitive.
  201.     put: QEstr
  202.     >uc: QEstr            \ QE needs all upper case for this
  203.     'type FIND send: self ;m
  204.     
  205. ;class
  206.  
  207. QE tQE        \ we now have just one object for sending commands to Quick Edit
  208.  
  209.  
  210. : inittQE
  211.     instld?  ?EXIT            \ Mustn't do this in installed apps
  212.     AppleEvents?  0EXIT
  213.     new: tQE  ;
  214.  
  215. inittQE
  216.  
  217. ' inittQE add: init_actions
  218.  
  219. endload
  220.  
  221. +echo
  222.  
  223. file testfile
  224.  
  225. : GO1
  226.     'type TEXT 1 stdget: testfile .  cr
  227.     testfile 10 20  openFile: tQE . ;
  228.  
  229. : GO2
  230.     " Hello World" text: tQE cr: tQE . ;    \ note how we must always end with a cr: to send:
  231.  
  232. : GO3
  233.     " My File Name" newwindow: tQE . ;
  234.  
  235. : GO4
  236.     100 50 300 350 putrect: tQE . ;
  237.  
  238. endload
  239.  
  240. ****** GENERAL COMMENTS *******
  241.  
  242.  
  243. It is very important to understand the "trick" being used here for communication between Mops and 
  244. QE.  We follow Apple's recipe for everything except for the descriptor record scheme.  Instead of 
  245. building and then deciphering the seemingly overly complex descriptor records for each AE, it seemed 
  246. to me to be much more straightforward to just send a handle to whatever data structure we wish.  
  247. Since we control everything at both ends (Mops and QE), then why go through all of the gyrations of 
  248. the AEdesc record handling?  We avoid having to deal with any of the AEPutParam/AEGetParam etc.  
  249. Also, we don't even have to deal with AEInstallEventHandler or AEProcessAppleEvent!
  250.  
  251. What we do is to only define our AppleEvents by class and not by also providing an ID.  This does 
  252. not seem to be much of a limitation on defining AEs since there are certainly plenty of different 
  253. classes we could define with the 32 bit class identifier.  Most importantly, we have now freed up 
  254. the ID of our AE for use in any way that we wish, and we wish to make our ID the handle to the data 
  255. we want to pass from Mops to QE or vice versa.  I don't know what kind of problems this could cause.  
  256. To date, I have noticed no problems.  But this does not seem to be the way Apple intended.  So 
  257. beware.  Note that both Mops and QE accomplish AE communication in exactly the same (non-standard) 
  258. way.  
  259.  
  260. The memory problem that both QE 2.4 and the original Mops 2.4 release suffered was not related
  261. to this scheme.  That problem existed due to the lack of understanding on my part of the need for
  262. disposing AppleEvents and AE Replies after each AESend.  But note that we do not need to create
  263. and dispose our descriptor record itself.  But we must use AEDisposeDesc to dispose of the 
  264. AppleEvent and AEReply ( no AEDisposeAppleEvent exists, apparently).
  265.  
  266. -Doug Hoffman  \ 12Feb94